package com.sunsharing.transport;

import com.sunsharing.common.Constant;
import com.sunsharing.common.Context;
import com.sunsharing.common.URL;
import com.sunsharing.common.anno.AnoClassCretator;
import com.sunsharing.common.mailbox.Mailbox;
import com.sunsharing.common.mailbox.QueueHandle;
import com.sunsharing.common.mailbox.memory.MemoryMailBox;
import org.apache.log4j.Logger;

/**
 * 通道：都有mailbox，一个进，一个出
 * User: criss
 * Date: 13-3-31
 * Time: 下午9:48
 * To change this template use File | Settings | File Templates.
 */
public abstract class Channel {
    Logger logger = Logger.getLogger(Channel.class);
    public URL url;

    Mailbox inbox;
    Mailbox outbox;
    /**输入的处理*/
    public IoHandle ioHandle;

    public IoHandle getIoHandle() {
        return ioHandle;
    }

    public void setIoHandle(IoHandle ioHandle) {
        this.ioHandle = ioHandle;
    }

    public void send(Context context)
    {
        //logger.error("outbox!!!!!!!!!!!!!!!!!!!!!!!!!!!!"+outbox);
        if(outbox!=null)
        {
            outbox.addQueue(context);
        }else
        {
            this.sendMsg(context);
        }
    }
    public void receive(Context context)
    {
        if(inbox!=null)
        {
            logger.info("添加到Inbox");
            inbox.addQueue(context);
        }
    }

    public URL getUrl() {
        return url;
    }

    public void setUrl(URL url) {
        this.url = url;
    }


    private void initInMailBox()
    {
        logger.info("初始化InMailBox");
        //初始化消息队列
        this.inbox = (Mailbox)AnoClassCretator.getInstance().createObject(Mailbox.class,Constant.MAILBOX_MEM,new Class[]{
                URL.class,Boolean.class},new Object[]{url,true});

        this.inbox.addQueueListener(ioHandle);
        this.inbox.startListen();
    }


    private void initOutMailBox()
    {
        logger.info("初始化OutMailBox");
         if(this.outbox==null)
         {
             //初始化消息队列
             this.outbox = (Mailbox)AnoClassCretator.getInstance().createObject(Mailbox.class,Constant.MAILBOX_MEM,new Class[]{
                         URL.class,Boolean.class},new Object[]{url,false});
             QueueHandle outHandle = new QueueHandle() {
                 @Override
                 public void run(Context context) {
                     try
                     {
                         sendMsg(context);
                     }catch (Exception e)
                     {
                         logger.error("发送失败重新来,添加队列",e);
                         context.addRetry();
                         if(!context.stopRety())
                         {
                             outbox.addQueue(context);
                             try
                             {
                                 Thread.sleep(1000);
                             }catch (Exception e2)
                             {

                             }
                         } else
                         {
                             logger.error("超过重试次数丢弃或者持久化",e);
                         }
                     }
                 }

                 public void doConnect()
                 {

                 }

             };
             this.outbox.addQueueListener(outHandle);
             this.outbox.startListen();
         }
    }

    public void initMailBox()
    {
        String client = url.getIsClient();
        String byclient = url.getByClient();
        if(byclient.equals("true"))
        {
            this.initOutMailBox();
            this.initInMailBox();
        }else
        {
            if(client.equals("true"))
            {
                this.initOutMailBox();
            }else
            {
                this.initInMailBox();
            }
        }
    }

    public void restartMailBox()
    {
        String client = url.getIsClient();
        String byclient = url.getByClient();
        if(byclient.equals("true"))
        {
             if(this.inbox==null)
             {
                 initInMailBox();
             }
             if(this.outbox==null)
             {
                initOutMailBox();
             }
        }else
        {
            if(client.equals("true"))
            {
                if(this.outbox==null)
                {
                    initOutMailBox();
                }
            }else
            {
                if(this.inbox==null)
                {
                    initInMailBox();
                }
            }
        }
        if(this.inbox!=null)
        {
            this.inbox.stopListen();
            this.inbox.startListen();
        }
        if(this.outbox!=null)
        {
            this.outbox.stopListen();
            this.outbox.startListen();
        }
    }

    abstract public void clone(Channel ch);
    abstract  public void reconnect();


    public void stop()
    {
        if(inbox!=null)
        {
            try
            {
                inbox.stopListen();
            }catch (Exception e)
            {

            }
        }
        if(outbox!=null)
        {
            try
            {
                outbox.stopListen();
            }catch (Exception e)
            {

            }
        }
    }
    abstract protected void sendMsg(Context context);
    abstract  public boolean isclose();

    private String getFromNode()
    {
        return url.getFromNodeId();
    }

    private String getChannelName()
    {
        return url.getChannelName();
    }

    private String getToNode()
    {
        return url.getToNodeId();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Channel)) return false;

        Channel channel = (Channel) o;

        if (getFromNode() != null ? !getFromNode().equals(channel.getFromNode()) : channel.getFromNode() != null) return false;
        if (getToNode() != null ? !getToNode().equals(channel.getToNode()) : channel.getToNode() != null) return false;
        if (getChannelName() != null ? !getChannelName().equals(channel.getChannelName()) : channel.getChannelName() != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = getChannelName() != null ? getChannelName().hashCode() : 0;
        result = 31 * result + (getChannelName() != null ? getChannelName().hashCode() : 0);
        result = 31 * result + (getFromNode() != null ? getFromNode().hashCode() : 0);
        result = 31 * result + (getToNode() != null ? getToNode().hashCode() : 0);
        return result;
    }

    public String toMonitor()
    {
        StringBuffer str = new StringBuffer();
        if(this.inbox!=null)
        {
            str.append("输入队列监控信息------------------");
            str.append(this.inbox.monitorStr());
        }
        if(this.outbox!=null)
        {
            str.append("输出队列监控信息------------------");
            str.append(this.outbox.monitorStr());
        }
        return str.toString();
    }
}
